package br.com.localfloripa.controllers;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.primefaces.model.DualListModel;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;

import br.com.localfloripa.dao.AnuncioDao;
import br.com.localfloripa.dao.ClienteDao;
import br.com.localfloripa.dao.PerfilDao;
import br.com.localfloripa.dao.UsuarioDao;
import br.com.localfloripa.entities.Cliente;
import br.com.localfloripa.entities.Perfil;
import br.com.localfloripa.entities.Servico;
import br.com.localfloripa.entities.Usuario;

@Named("usuarioController")
@Scope("session")
public class UsuarioController implements Serializable {

	private static final long serialVersionUID = -5032439479613861822L;
	private static final Logger log = LoggerFactory.getLogger(UsuarioController.class);
	private final Integer pageSize = 10;
	
	@Inject
	@Named("usuarioDao")
	private UsuarioDao usuarioDao;
	
	@Inject
	@Named("clienteDao")
	private ClienteDao clienteDao;
	
	@Inject
	@Named("perfilDao")
	private PerfilDao perfilDao;
	
	@Inject
	@Named("anuncioDao")
	private AnuncioDao anuncioDao;
	
	private LazyDataModel<Usuario> lazyModelUsuario;
	private Usuario usuario;
	
	private List<Cliente> clientes;
	private DualListModel<Perfil> perfis;
	
	/** controla linha selecionada do dataTable **/
	private boolean selectedUsuario = false;

	public UsuarioController() {
		
	}
	
	@PostConstruct
	public void loadModels() {
		lazyModelUsuario = new LazyDataModel<Usuario>() {

			@Override
			public int getPageSize() {
				return pageSize;
			}

			@Override
			public int getRowCount() {
				return usuarioDao.countListUsuarios().intValue();
			}

			@Override
			public List<Usuario> load(int first, int pageSize, String sortField, SortOrder order, Map<String, String> filters) {
				List<Usuario> usuarios = null;
				try {
					usuarios = usuarioDao.listUsuariosPaginada(first, pageSize);
				} catch (Exception e) {
					log.error(e.getMessage(),e);
				}
				return usuarios;
			}	
			
			@Override  
		    public Object getRowKey(Usuario usuario) {  
		        return usuario.getId();  
		    } 
			
			@Override  
		    public Usuario getRowData(String rowKey) {  
				
				if (rowKey != null && !rowKey.equals("null")) {
					List<Usuario> usuarios = (List<Usuario>) getWrappedData();  
			          
			        for(Usuario usuario : usuarios) {  
			            if(usuario.getId().equals(Long.valueOf(rowKey)))  
			                return usuario;  
			        }
				}  		          
		        return null;  
		    }  
		};
	}
	
	public String login() {
		
		try {
			HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
			HttpServletResponse response = (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
			RequestDispatcher dispatcher = request.getRequestDispatcher("/j_spring_security_check");
			dispatcher.forward(request, response);
			FacesContext.getCurrentInstance().responseComplete();
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			return null;
		}
		return null;		
	}
	
	public String logout() {
		try {
			HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
			HttpServletResponse response = (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
			RequestDispatcher dispatcher = request.getRequestDispatcher("/j_spring_security_logout");
			dispatcher.forward(request, response);
			FacesContext.getCurrentInstance().responseComplete();
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			return null;
		}
		return null;
	}
	
	public String create() {
		
		this.usuario = new Usuario();
		try {
			this.clientes = clienteDao.listClientesOrdemNome();
			List<Perfil> source = perfilDao.listAllPerfis();
			List<Perfil> target = new ArrayList<Perfil>();
			this.perfis = new DualListModel<Perfil>(source,target);
		} catch (Exception e) {
			log.error(e.getMessage());
			this.clientes = new ArrayList<Cliente>();
			this.perfis = new DualListModel<Perfil>();
		}
		return "/faces/manager/xhtml/usuario/create.xhtml";
	}
	
	public String edit() {		
		try {
			if (this.usuario != null) {
				this.clientes = clienteDao.listClientesOrdemNome();				
				List<Perfil> source = merge(perfilDao.listAllPerfis(), this.usuario.getPerfis());
				List<Perfil> target = this.usuario.getPerfis();
				this.perfis = new DualListModel<Perfil>(source,target);
				if (this.usuario.getCliente() == null)
					this.usuario.setCliente(new Cliente());				
				return "/faces/manager/xhtml/usuario/update.xhtml";
			} else {
				ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageBundle");
				FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
						bundle.getString("messages.sumary.error"), bundle.getString("manager.usuario.edit.error")));
				return "/faces/manager/xhtml/usuario/list.xhtml";
			}
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			return "/faces/manager/xhtml/usuario/list.xhtml";
		}
	}
	
	private List<Perfil> merge(List<Perfil> listPerfilOriginal,List<Perfil> listPerfilUsuario) {
		
		List<Perfil> mergeList = listPerfilOriginal;		
		for (Perfil perfilUsuario : listPerfilUsuario) {	
			if (mergeList.contains(perfilUsuario)) {
				mergeList.remove(perfilUsuario);
			}
		}
		return mergeList;		
	}
	
	public String save() {
		ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageBundle");
		try {
			this.usuario.setPerfis(this.perfis.getTarget());
			if (this.usuario.getCliente().getId() > 0) {
				this.usuario.setCliente(clienteDao.findById(this.usuario.getCliente().getId()));
			} else {
				this.usuario.setCliente(null);
			}
			usuarioDao.persist(this.usuario);
			loadModels();
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.info.confirm"), bundle.getString("manager.usuario.create.confirm")));  
			return "/faces/manager/xhtml/usuario/list.xhtml";
		} catch (Exception e) {
			log.error(e.getMessage());
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.error"), bundle.getString("manager.usuario.create.error"))); 
			return "/faces/manager/xhtml/usuario/create.xhtml";
		}
	}
	
	public String update() {
		ResourceBundle bundle = ResourceBundle.getBundle("messages.MessageBundle");
		try {
			this.usuario.setPerfis(this.perfis.getTarget());
			if (this.usuario.getCliente().getId() > 0) {
				this.usuario.setCliente(clienteDao.findById(this.usuario.getCliente().getId()));
			} else {
				this.usuario.setCliente(null);
			}
			usuarioDao.merge(this.usuario);
			loadModels();
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.info.confirm"), bundle.getString("manager.usuario.update.confirm")));  
			return "/faces/manager/xhtml/usuario/list.xhtml";
		} catch (Exception e) {
			log.error(e.getMessage());
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
					bundle.getString("messages.sumary.error"), bundle.getString("manager.usuario.update.error"))); 
			return "/faces/manager/xhtml/usuario/update.xhtml";
		}
	}

	public Integer getPageSize() {
		return pageSize;
	}

	public Usuario getUsuario() {
		return usuario;
	}

	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

	public LazyDataModel<Usuario> getLazyModelUsuario() {
		return lazyModelUsuario;
	}

	public void setLazyModelUsuario(LazyDataModel<Usuario> lazyModelUsuario) {
		this.lazyModelUsuario = lazyModelUsuario;
	}

	public List<Cliente> getClientes() {
		return clientes;
	}

	public void setClientes(List<Cliente> clientes) {
		this.clientes = clientes;
	}

	public DualListModel<Perfil> getPerfis() {
		return perfis;
	}

	public void setPerfis(DualListModel<Perfil> perfis) {
		this.perfis = perfis;
	}
	
	public boolean isSelectedUsuario() {
		return selectedUsuario;
	}

	public void onSelectedRow() {
		this.selectedUsuario =  true; 
	}
	
	public void onPaged() {
		this.selectedUsuario = false;
	}

	public Boolean getLimiteAnuncios() {
		
		try {
			Usuario usuarioLogado = Usuario.getLoggedUser();
			if (!usuarioLogado.hasRole("ADMIN"))
				return usuarioLogado.getCliente().getPlano() < getCountAnunciosAtivos(usuarioLogado.getCliente());			
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}		
		return false;		
	}
	
	private int getCountAnunciosAtivos(Cliente cliente) {			
		Integer anunciosAtivos = anuncioDao.countAnunciosByCliente(cliente).intValue(); 
		return anunciosAtivos != null ? anunciosAtivos : 0;
	}
	
	
}
